<?php

class Session {

    /**
     * redis数据库配置数组
     *
     * @var array
     */
    private $db;

    /**
     * 用户的key
     *
     * @var string
     */
    private $key;

    /**
     * 与redis同步的cache缓存对象
     *
     * @var array
     */
    private $cache;

    /**
     * 如果session不存在时的初始化值
     *
     * @var array
     */
    private $default = [

        // app信息组
        'appname'=> '',                 // app名称
        'appversion'=> '',              // app版本号
        'platform'=> '',                // 平台名称：weapp, rn, h5

        // 设备信息组
        'brand'=> '',                   // 品牌
        'model'=> '',                   // 型号
        'os'=> '',                      // 操作系统
        'osversion'=> '',               // 操作系统版本号
        'width'=> 0,                    // 屏幕宽度
        'height'=> 0,                   // 屏幕高度
        'language'=> '',                // 系统语言

        // 网络信息组
        'carrier'=> '',                 // 网络运营商（小程序和h5抓取不到）：中国联通, 中国电信
        'networktype'=> '',             // wifi, 2g, 3g, 4g, unknown, none
        'ip'=> '',                      // ip地址

        // 用户信息组
        'arriveid'=> '',                // 到达id编号
        'userid'=> 0,                   // 用户id号，匿名用户为0
        'lat'=> '',                     // 用户所在经度
        'lon'=> '',                     // 用户所在纬度
        'nation'=> '',                  // 国家
        'provionce'=> '',               // 省
        'city'=> '',                    // 城市
        'district'=> '',                // 区县
        'street'=> '',                  // 街道
        'street_number'=> '',           // 街道编号 
        'address'=> '',                 // 详细地址
    ];

    /**
     * 过期秒数为1200（20分钟）
     *
     * @var integer
     */
    private $timeout = 1200;

    /**
     * 初始化
     */
    public function __construct() {
        $this->db = RDB_SESSION;
        $this->key = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    }

    /**
     * 初始化用户session
     *
     * @return void
     */
    public function init() {

        // 如果httpAuth头不正确，则返回false以报错
        if ($this->key == '') {
            return Section::fail('没有完整的权限验证参数！');
        }

        // 分解key为数组，并验证长度
        $tmp = LString::split($this->key, ' ');
        if (LString::len($tmp[0]) != 32) {
            return Section::fail('没有完整的权限验证参数！');
        }
        $this->key = $tmp[0];
        
        // 取redis实例
        $redis = Rdb::pconnect($this->db);

        // 如果存在redis实例，则指定到$this->cache，并设置过期时间
        if ($redis->exists($this->key)) {
            $this->cache = $redis->hGetAll($this->key);
        }

        // 如果不存在此key，则将cache初始化为初始session（带有time时间戳的数组）
        else {
            $this->cache = $this->default;
            $redis->hMSet($this->key, $this->cache);            
        }
        

        // 设置redis过期时间 
        $redis->setTimeout($this->key, $this->timeout);

        // 初始化成功，返回true
        return Section::ok();
    }

    /**
     * 获取session中的一个条目
     *
     * @return any
     */
    public function getItem(string $key) {
        // $redis = Rdb::pconnect($this->db);
        // return $redis->hget($this->key,$key);
        return $this->cache[$key] ?? null;
    }

    /**
     * 添加或设置session中的一个条目的值
     *
     * @param string $key 键名
     * @param any $value 值
     * @return void
     */
    public function setItem(string $key, $value) {
        // 设置缓存cache
        $this->cache[$key] = json_encode($value);

        // 设置redis
        $redis = Rdb::pconnect($this->db);
        $redis->hSet($this->key, $key, $value);
    }

    /**
     * 删除一个session
     *
     * @param string $key 键名
     * @return void
     */
    public function delItem(string $key) {
        // 设置缓存cache
        unset($this->cache[$key]);

        // 设置redis
        $redis = Rdb::pconnect($this->db);
        $redis->hDel($this->key, $key);
    }

    /**
     * 获取session的所有条目
     *
     * @return array
     */
    public function getAll() {
        return $this->cache;
    }

    /**
     * 设置session中的所有条目
     *
     * @return void
     */
    public function setAll($value) {
        // 设置缓存cache
        $this->cache = $value;

        // 设置redis
        $redis = Rdb::pconnect($this->db);
        $redis->hDel($this->key, $this->cache);
    }

    /**
     * 删除session中的所有条目
     *
     * @return void
     */
    public function clear() {
        // 设置缓存cache
        $this->session = [];

        // 设置redis
        $redis = Rdb::pconnect($this->db);
        $redis->delete($this->key);
    }
}
